package utils

import (
	"encoding/json"
	"errors"
	"log"
	"math/rand"
	"os"
	"path"
	"regexp"
	"time"
)

//获取长度为len的随机字符串
func GetRandomString(len int) string {
	r := rand.New(rand.NewSource(time.Now().Unix()))
	res := make([]byte, len)
	for i := 0; i < len; i++ {
		res[i] = byte(r.Intn(26) + 65)
	}
	return string(res)
}

//查错，出错后退出，此函数会被编译器优化为内联
func CheckErr(err error) {
	if err != nil {
		log.Println(err)
		os.Exit(1)
	}
}

type Dir struct {
	Name  string `json:"dirName"`
	Child []*Dir `json:"childDir"`
}

// GetUserHomeDirPath 获取用户目录
func GetUserHomeDirPath() (string, error) {
	userDir, err := os.UserHomeDir()
	if err != nil {
		return userDir, err
	}
	rootDir := new(Dir)
	rootDir.Name = userDir
	rootDir.Child = make([]*Dir, 0)
	var getChildDIrInfo func(parent *Dir, base string)
	getChildDIrInfo = func(parent *Dir, base string) {
		dirEntry, err := os.ReadDir(path.Join(base, parent.Name))
		CheckErr(err)
		for _, i := range dirEntry {
			if i.IsDir() {
				if i.Name()[0] != '.' {
					newDir := new(Dir)
					newDir.Name = i.Name()
					newDir.Child = make([]*Dir, 0)
					parent.Child = append(parent.Child, newDir)
					getChildDIrInfo(newDir, path.Join(base, parent.Name))
				}
			}

		}
	}
	getChildDIrInfo(rootDir, "/")
	res, _ := json.Marshal(rootDir)
	return string(res), err
}

type dirInfo struct {
	Name  string `json:"name"`
	IsDir bool   `json:"is_dir"`
}

// GetPath 获取用户目标目录子文件夹
func GetPath(base string) (string, error) {
	homeDir, err := os.UserHomeDir()
	if err != nil {
		log.Println(err)
		os.Exit(1)
	}
	aimPath := path.Join(homeDir, base)
	pattern := "^" + homeDir + ".*$"
	ok, err := regexp.MatchString(pattern, aimPath)
	if err != nil {
		return "", err
	}
	if !ok {
		var err = errors.New("目标目录超出用户目录，拒绝访问")
		return "", err
	}
	dirInfos, err := os.ReadDir(aimPath)
	if err != nil {
		return "", err
	}
	info := make([]*dirInfo, 0)
	for _, value := range dirInfos {
		if value.Name()[0] != '.' {
			info = append(info, &dirInfo{
				Name:  value.Name(),
				IsDir: value.IsDir(),
			})
		}
	}
	res, err := json.Marshal(info)
	if err != nil {
		return "", err
	}
	return string(res), nil
}
